package server

import (
	"context"
	"errors"
	"fmt"
	"huijing_mall/internal/cachebase"
	"huijing_mall/internal/database"
	"huijing_mall/internal/mq"
	"huijing_mall/shared/get_ctx_value"
	"huijing_mall/variable"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	mysqlCfg "github.com/go-sql-driver/mysql"
	"github.com/redis/go-redis/v9"
	"github.com/robfig/cron/v3"

	"huijing_mall/scripts"

	"github.com/gin-gonic/gin"
)

func Run(port string, mysql *mysqlCfg.Config, redis *redis.Options, mq *mq.RabbitMQ, r func(router *gin.Engine)) {
	mysql.Net = "tcp"
	mysql.Params["parseTime"] = "True"
	db := database.InitDB(mysql)
	rdb := cachebase.InitRedis(redis)
	// 声明队列
	//if err := mq.DeclareQueue(variable.SendQu); err != nil {
	//	logger.Error(fmt.Sprintf("声明队列 %s 失败: %v", variable.SendQu, err))
	//}
	//if err := mq.DeclareQueue(variable.TaskQu); err != nil {
	//	logger.Error(fmt.Sprintf("声明队列 %s 失败: %v", variable.TaskQu, err))
	//}
	dbs := &get_ctx_value.DBS{DB: db, Rdb: rdb, Mq: mq}
	//mq
	//go consume.StartMQConsumers(mq, dbs)
	//定时任务
	obj := script.CronObj{CronCtx: cron.New(), DBS: dbs}
	go obj.SetTimeTask()
	get_ctx_value.DBMap = make(map[int]*get_ctx_value.DBS)
	get_ctx_value.DBMap[0] = dbs
	// 设置为发布模式（去掉调试信息）
	gin.SetMode(gin.ReleaseMode)
	//gin
	system := gin.New()
	//中间件  携带一些东西
	system.Use(func(g *gin.Context) {
		g.Set(variable.DBS, dbs)
		g.Next()
	})
	r(system)
	//r := gin.Default()
	srv := &http.Server{
		Addr:    ":" + port,
		Handler: system,
		//ReadTimeout:  30 * time.Second,暂时不使用
		//WriteTimeout: 30 * time.Second,
		//IdleTimeout:  30 * time.Second,
	}

	processed := make(chan struct{})
	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt, syscall.SIGTERM)
		<-c
		fmt.Println("ctrl + c")
		ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
		defer cancel()
		if err := srv.Shutdown(ctx); nil != err {
			log.Fatalf("server shutdown failed, err: %v\n", err)
		}
		log.Println("server gracefully shutdown")

		processed <- struct{}{}
	}()

	if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
		fmt.Printf("ListenAndServe error: %v\n", err)
	}

}
